home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1998 July / EnigmA AMIGA RUN 29 (1998)(G.R. Edizioni)(IT)[!][issue 1998-07 & 08].iso / recent / gms_pi.lha / Pictures / PIC_Functions.c < prev    next >
C/C++ Source or Header  |  1998-06-22  |  11KB  |  385 lines

  1.  
  2. #include <proto/dpkernel.h>
  3. #include <system/all.h>
  4. #include <dpkernel/prefs.h>
  5. #include "defs.h"
  6.  
  7. /***********************************************************************************
  8. ** Internal: UnpackPicture()
  9. **
  10. ** Unpacks the BODY data to the Picture->Bitmap.  If the palettes or amount of
  11. ** colours do not match, the picture will be automatically remapped.
  12. */
  13.  
  14. LONG UnpackPicture(struct Picture *Picture, struct BMHD *BMHD,
  15.                    struct File *File, LONG *CMAP, LONG CAMG)
  16. {
  17.   struct Bitmap *Bitmap;
  18.   struct Bitmap *ILBMBitmap = NULL;
  19.   WORD   MaxWidth;
  20.   LONG   Colour;
  21.   WORD   i, y, j, ydest;
  22.   WORD   XRemainder, YRemainder, Domain;
  23.   LONG   AmtColours;
  24.   LONG   *Palette = NULL;
  25.   BYTE   *DestPalette;
  26.   BYTE   *SrcPalette;
  27.   BYTE   *SrcBData;
  28.   BYTE   *DestBData;
  29.   APTR   BLTBase = GVBase->BlitterBase;
  30.   WORD   Height;
  31.   WORD   BPos;
  32.   BYTE   *Dest;
  33.   BYTE   *Buffer = NULL;
  34.   LONG   ecode = ERR_FAILED;
  35.  
  36.   DPrintF("UnpackPicture()","Unpacking ILBM picture to destination...");
  37.  
  38.   if (Picture->Options & IMG_RESIZE) {
  39.      DPrintF("UnpackPicture:","Note that the image will need to be resized.");
  40.   }
  41.  
  42.   DPrintF("UnpackPicture:","Allocating an unpack buffer of %ld bytes.",UNPACKSIZE);
  43.  
  44.   if ((Buffer = AllocMemBlock(UNPACKSIZE, MEM_DATA)) IS NULL) {
  45.      goto exit;
  46.   }
  47.  
  48.   Bitmap     = Picture->Bitmap;
  49.   YRemainder = NULL;
  50.  
  51.   if ((Height = Bitmap->Height) > BMHD->Height) {
  52.      Height = BMHD->Height;
  53.   }
  54.  
  55.   /*** Calculate the amount of colours in the ILBM BMHD source. ***/
  56.  
  57.   if (CMAP) {
  58.      if ((BMHD->Depth < 1) OR (BMHD->Depth > 8)) {
  59.         DPrintF("!UnpackPicture:","Incorrect/Unsupported plane depth (%d).",BMHD->Depth);
  60.      }
  61.  
  62.      AmtColours = 1;
  63.      for (i=0; i < BMHD->Depth; i++) {
  64.          AmtColours *= 2;
  65.      }
  66.  
  67.      /* Build the palette here and use it in the ILBM Bitmap.  This is
  68.      ** necessary for ReadRGBPixel() functions which we use further down.
  69.      */
  70.  
  71.      if (Palette = AllocMemBlock((AmtColours * 4)+8,MEM_DATA)) {
  72.         Palette[0] = PALETTE_ARRAY;
  73.         Palette[1] = AmtColours;
  74.  
  75.         SrcPalette  = (BYTE *)CMAP;
  76.         DestPalette = ((BYTE *)Palette)+8;
  77.         for (i=0; i < AmtColours; i++) {
  78.            DestPalette[1] = SrcPalette[0];
  79.            DestPalette[2] = SrcPalette[1];
  80.            DestPalette[3] = SrcPalette[2];
  81.            DestPalette += 4;
  82.            SrcPalette  += 3;
  83.         }
  84.      }
  85.      else goto exit;
  86.   }
  87.  
  88.   DPrintF("UnpackPicture:","Allocating dummy Bitmap.");
  89.  
  90.   if (!(ILBMBitmap = InitTags(NULL,
  91.        TAGS_BITMAP, NULL,
  92.        BMA_Width,   BMHD->Width,
  93.        BMA_Height,  1,
  94.        BMA_Planes,  BMHD->Depth,
  95.        BMA_Type,    ILBM,
  96.        BMA_Palette, Palette,
  97.        TAGEND))) {
  98.        goto exit;
  99.   }
  100.  
  101.   /*** Force remapping if colours or palettes are different ***/
  102.  
  103.   if (!(Picture->Options & IMG_REMAP)) {
  104.      if (Bitmap->AmtColours != ILBMBitmap->AmtColours) {
  105.         Picture->Options |= IMG_REMAP;
  106.      }
  107.      else { /* Compare palettes */
  108.         for (i=2; i < (Bitmap->AmtColours+2); i++) {
  109.            if (Bitmap->Palette[i] != ILBMBitmap->Palette[i]) {
  110.               Picture->Options |= IMG_REMAP;
  111.               i = 30000; /* Terminate the loop */
  112.            }
  113.         }
  114.      }
  115.   }
  116.  
  117.   if (Picture->Options & IMG_REMAP) {
  118.      DPrintF("UnpackPicture:","Colour remapping for this Picture is in effect.");
  119.   }
  120.  
  121.   /*** Calculate some initial variables for the loop ***/
  122.  
  123.   if (Bitmap->Width < ILBMBitmap->Width) {
  124.      MaxWidth = Bitmap->Width;
  125.   }
  126.   else {
  127.      MaxWidth = ILBMBitmap->Width;
  128.   }
  129.   ydest = NULL;
  130.  
  131.   /* Begin the loop now.  Unpack one row at a time to the ILBM Bitmap
  132.   ** buffer, then copy the pixels from the buffer over to our destination.
  133.   */
  134.  
  135.   BPos = NULL;
  136.   Read(File, Buffer, UNPACKSIZE);
  137.  
  138.   for (y=0; y < Height; y++) {
  139.  
  140.      /*** Unpack the body data to our special ILBM Bitmap ***/
  141.  
  142.      if ((BMHD->Depth IS 8) AND (CAMG & OSV_HAM)) {
  143.         Dest = ((BYTE *)ILBMBitmap->Data) + (ILBMBitmap->ByteWidth * 2);
  144.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos); Dest += ILBMBitmap->ByteWidth;
  145.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos); Dest += ILBMBitmap->ByteWidth;
  146.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos); Dest += ILBMBitmap->ByteWidth;
  147.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos); Dest += ILBMBitmap->ByteWidth;
  148.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos); Dest += ILBMBitmap->ByteWidth;
  149.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos);
  150.  
  151.         Dest = ILBMBitmap->Data;
  152.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos); Dest += ILBMBitmap->ByteWidth;
  153.         BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos);
  154.      }
  155.      else {
  156.         Dest = ILBMBitmap->Data;
  157.         for (j=0; j < ILBMBitmap->Planes; j++) {
  158.            BPos = UnpackPlane(BMHD, File, ILBMBitmap, Dest, Buffer, BPos);
  159.            Dest += ILBMBitmap->ByteWidth;
  160.         }
  161.      }
  162.  
  163.      /* Write the data out to the destination Bitmap.  If resizing,
  164.      ** we use the standard DrawPixel() and ReadPixel() routines.  Although
  165.      ** we could improve the speed in some parts, it is not too crucial.
  166.      */
  167.  
  168.      if ((Picture->Options & IMG_RESIZEX) AND (Bitmap->Width != ILBMBitmap->Width)) {
  169.         if (ILBMBitmap->Width > Bitmap->Width) { /*** Shrink Row ***/
  170.            XRemainder = NULL;
  171.            Domain = ILBMBitmap->Width - Bitmap->Width;
  172.            j = NULL;
  173.  
  174.            for (i=0; i < Bitmap->Width; i++) {
  175.               XRemainder += Domain;
  176.  
  177.               while (XRemainder >= Bitmap->Width) {
  178.                  XRemainder -= Bitmap->Width;
  179.                  j++;
  180.               }
  181.               DrawRGBPixel(Bitmap,i,ydest,ReadRGBPixel(ILBMBitmap,j++,0));
  182.            }
  183.         }
  184.         else { /*** Expand Row ***/
  185.            XRemainder = NULL;
  186.            Domain = Bitmap->Width - ILBMBitmap->Width;
  187.            j = NULL;
  188.  
  189.            for (i=0; i < ILBMBitmap->Width; i++) {
  190.               Colour = ReadRGBPixel(ILBMBitmap,i,0);
  191.               DrawRGBPixel(Bitmap,j++,ydest,Colour);
  192.               XRemainder += Domain;
  193.  
  194.               while (XRemainder >= ILBMBitmap->Width) {
  195.                  DrawRGBPixel(Bitmap,j++,ydest,Colour);
  196.                  XRemainder -= ILBMBitmap->Width;
  197.               }
  198.            }
  199.         }
  200.      }
  201.      else if (Picture->Options & IMG_REMAP) {
  202.         for (i=0; i < MaxWidth; i++) {
  203.             DrawRGBPixel(Bitmap,i,ydest,ReadRGBPixel(ILBMBitmap,i,0));
  204.         }
  205.      }
  206.      else if ((Bitmap->Type IS PLANAR) OR (Bitmap->Type IS ILBM)) {
  207.         /* This routine takes advantage of the fact that PLANAR and ILBM
  208.         ** store pixels in sets of 8 per byte.
  209.         */
  210.  
  211.         SrcBData  = (BYTE *)ILBMBitmap->Data;
  212.         DestBData = ((BYTE *)Bitmap->Data) + (Bitmap->LineMod * ydest);
  213.         for (j=0; j < ILBMBitmap->Planes; j++) {
  214.            for (i=0; i < ((MaxWidth+15) & 0xFFF0)/8; i++) {
  215.               DestBData[i] = SrcBData[i];
  216.            }
  217.            SrcBData  += ILBMBitmap->ByteWidth;
  218.            DestBData += Bitmap->PlaneMod;
  219.         }
  220.      }
  221.      else if (Bitmap->Type IS CHUNKY8) {
  222.         DestBData = ((BYTE *)Bitmap->Data) + (Bitmap->ByteWidth * ydest);
  223.         for (i=0; i < MaxWidth; i++) {
  224.            DestBData[i] = ReadPixel(ILBMBitmap,i,0); /* Convert ILBM to Chunky */
  225.         }
  226.      }
  227.      else { /* CHUNKY16 and TRUECOLOUR types require RGB to read from ILBM */
  228.         for (i=0; i < MaxWidth; i++) {
  229.             DrawRGBPixel(Bitmap,i,ydest,ReadRGBPixel(ILBMBitmap,i,0));
  230.         }
  231.      }
  232.  
  233.      /*** Image Resizing Y Axis ***/
  234.  
  235.      if (Picture->Options & IMG_RESIZEY) {
  236.         if (Bitmap->Height < BMHD->Height) { /*** Shrink Down ***/
  237.            Domain      = BMHD->Height - Bitmap->Height;
  238.            YRemainder += Domain;
  239.            while (YRemainder >= Bitmap->Height) {
  240.               YRemainder -= Bitmap->Height;
  241.               BPos = SkipRow(BMHD, (BYTE *)Buffer, File, ILBMBitmap,BPos);
  242.            }
  243.         }
  244.         else if (Bitmap->Height > BMHD->Height) { /*** Expand ***/
  245.            Domain      = Bitmap->Height - BMHD->Height;
  246.            YRemainder += Domain;
  247.            while (YRemainder >= BMHD->Height) {
  248.               YRemainder -= BMHD->Height;
  249.               ydest++;
  250.               CopyLine(Bitmap,Bitmap,ydest-1,ydest,Bitmap->Width,0);
  251.            }
  252.         }
  253.      }
  254.      ydest++;
  255.   }
  256.  
  257.   ecode = ERR_OK;
  258.  
  259. exit:
  260.   if (Buffer)     FreeMemBlock(Buffer);
  261.   if (ILBMBitmap) Free(ILBMBitmap);
  262.   if (Palette)    FreeMemBlock(Palette);
  263.   return(ecode);  
  264. }
  265.  
  266. /***********************************************************************************
  267. ** Internal: SkipRow()
  268. ** Short:    Skips a complete line of Buffer data.
  269. */
  270.  
  271. WORD SkipRow(struct BMHD *BMHD, BYTE *Buffer, struct File *File, struct Bitmap *ILBMBitmap, WORD BPos)
  272. {
  273.   WORD written;
  274.   BYTE num;
  275.  
  276.   if (BMHD->Pack) {
  277.      written = NULL;
  278.      while (written < ILBMBitmap->ByteWidth) {
  279.         num = Buffer[BPos++];
  280.         if (BPos >= UNPACKSIZE) {
  281.            BPos = NULL;
  282.            Read(File, Buffer, UNPACKSIZE);
  283.         }
  284.  
  285.         if (num >= 0) {
  286.            do {
  287.               BPos++;
  288.               if (BPos >= UNPACKSIZE) {
  289.                  BPos = NULL;
  290.                  Read(File, Buffer, UNPACKSIZE);
  291.               }
  292.               num--;
  293.               written++;
  294.            } while (num >= 0);
  295.         }
  296.         else if (num != -128) {
  297.            num = -num;
  298.            BPos++;
  299.            if (BPos >= UNPACKSIZE) {
  300.               BPos = NULL;
  301.               Read(File, Buffer, UNPACKSIZE);
  302.            }
  303.  
  304.            do {
  305.               written++;
  306.               num--;
  307.            } while (num >= 0);
  308.         }
  309.      }
  310.   }
  311.   else {
  312.      for (num=0; num < ILBMBitmap->ByteWidth; num++) {
  313.         BPos++;
  314.         if (BPos >= UNPACKSIZE) {
  315.            BPos = NULL;
  316.            Read(File, Buffer, UNPACKSIZE);
  317.         }
  318.      }
  319.   }
  320.  
  321.   return(BPos);
  322. }
  323.  
  324. /***********************************************************************************
  325. ** Internal: UnpackPlane()
  326. ** Short:    Unpacks one plane of BODY data to the ILBMBitmap object.
  327. */
  328.  
  329. WORD UnpackPlane(struct BMHD *BMHD, struct File *File, struct Bitmap *ILBMBitmap, BYTE *Dest, BYTE *Buffer, WORD BPos)
  330. {
  331.   WORD written;
  332.   BYTE num, col;
  333.  
  334.   if (BMHD->Pack) {
  335.      written = NULL;
  336.      while (written < ILBMBitmap->ByteWidth) {
  337.         num = Buffer[BPos++];
  338.         if (BPos >= UNPACKSIZE) {
  339.            BPos = NULL;
  340.            Read(File, Buffer, UNPACKSIZE);
  341.         }
  342.  
  343.         if (num >= 0) {
  344.            do {
  345.               *Dest++ = Buffer[BPos++];
  346.               if (BPos >= UNPACKSIZE) {
  347.                  BPos = NULL;
  348.                  Read(File, Buffer, UNPACKSIZE);
  349.               }
  350.               num--;
  351.               written++;
  352.               if (written > ILBMBitmap->ByteWidth) return(BPos);
  353.            } while (num >= 0);
  354.         }
  355.         else if (num != -128) {
  356.            num = -num;
  357.            col = Buffer[BPos++];
  358.            if (BPos >= UNPACKSIZE) {
  359.               BPos = NULL;
  360.               Read(File, Buffer, UNPACKSIZE);
  361.            }
  362.  
  363.            do {
  364.               *Dest++ = col;
  365.               written++;
  366.               num--;
  367.               if (written > ILBMBitmap->ByteWidth) return(BPos);
  368.            } while (num >= 0);
  369.         }
  370.      }
  371.   }
  372.   else {
  373.      for (num=0; num < ILBMBitmap->ByteWidth; num++) {
  374.         *Dest++ = Buffer[BPos++];
  375.         if (BPos >= UNPACKSIZE) {
  376.            BPos = NULL;
  377.            Read(File, Buffer, UNPACKSIZE);
  378.         }
  379.      }
  380.   }
  381.  
  382.   return(BPos);
  383. }
  384.  
  385.